package main

import (
	"context"
	"github.com/gin-gonic/gin"
	"github.com/panjf2000/ants/v2"
	"log"
	"net/http"
	"os"
	"os/signal"
	"sgo/initializer"
	"sgo/middleware"
	"sgo/router"
	"sgo/scontext"
	"syscall"
	"time"
)

// @title 接口文档
// @version 1.0
// @description Sgo：基于Gin的快速开发脚手架
func main() {

	sgoContext := scontext.New("config.yaml")

	// 关闭程序释放资源
	defer scontext.Close(sgoContext)

	err := initializer.Initialize(sgoContext)

	if err != nil {
		log.Println("初始化SgoContext失败：", err)
		return
	}

	log.Println("初始化SgoContext成功...")

	gin.SetMode(gin.ReleaseMode)

	// 获取一个默认的引擎，包含Logger(), Recovery()两个中间件
	//engine := gin.Default()

	engine := gin.New()

	// 禁用代理信任，避免一些不必要的计算
	_ = engine.SetTrustedProxies(nil)

	engine.Use(gin.Recovery())

	// 注册中间件
	middleware.Use(sgoContext, engine)

	// 注册路由
	router.Use(sgoContext, engine)

	// 启动服务器
	srv := start(sgoContext, engine)

	// 优雅关闭
	listenAndStop(srv)
}

func start(sc *scontext.SgoContext, engine *gin.Engine) *http.Server {

	srv := new(http.Server)
	srv.Handler = engine
	srv.Addr = sc.ViperConfig.Server.Addr
	go func() {
		err := srv.ListenAndServe()
		if err != nil && err != http.ErrServerClosed {
			log.Println("服务器异常:", err)
			return
		}
	}()
	log.Println("服务器启动成功...")
	log.Println("http://" + sc.ViperConfig.Server.Addr)
	return srv
}

// 优雅关闭

func listenAndStop(srv *http.Server) {
	// 优雅关闭
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM,
		syscall.SIGQUIT, syscall.SIGKILL)
	<-quit

	log.Println("服务器关闭中，请稍等...")
	ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
	defer cancel()

	if err := srv.Shutdown(ctx); err != nil {
		log.Println("服务器关闭异常:", err)
		cancel()
	}

	select {
	case <-ctx.Done():
		release()
	}

	log.Println("服务器关闭成功...")
}

// 释放资源

func release() {

	// 释放ants协程资源
	ants.Release()
	log.Println("释放ants协程资源...")

	// todo 在此处是否其他资源

}
